<template>
	<div class='ex fv' :class='[ config.class ]' :style="{height:vn.setPx(config.height)}">
		<section ref='tableRef' class='jzer-table ex rel' :class="[
			!fn.hasArray(ajax.data) && !config.isChild ? 'mb10':'', 
			isAuto ? '' : 'jzer-table-scroll',
			(config.pag==false && !isAuto)||ajax?.data?.length === 0 ? 'bbor1':''
	]">
			<Table
				:columns 		= 'columns'
				:data-source 	= 'Array.isArray(ajax.data) ? ajax.data : []'
				:row-key 		= "(record, index) => record[idStr] || index"
				:size 			= 'size'
				:bordered 		= 'bordered'
				:scroll 		= "{ y: !fn.hasArray(ajax.data) || isAuto ? false : true, x:'100%' }"
				:loading 		= 'loading || ajax.loading'
				:pagination 	= 'false'
				:rowSelection 	= 'config.row ? { selectedRowKeys, ...rowSelection } : null'
				@change 		= 'onSort'
				:customRow 		= 'customRow'
				:rowClassName 	= "onRowClass"
				:expandRowByClick = 'true'
				@expand = 'config?.onExpand'
			>
				<template v-slot:controls='{ record, index }'>
					<Controls :align="config?.controls?.align ?? 'center'" :size="config?.controls?.size ?? 'small'" @click='v=>onControl(record, index, v)' isMyClick isTable :config='{ controls: config?.controls?.data?.(record, index) ?? [], perm:config.perm }' />
				</template>
				<template v-slot:controlsSelect='{ record, index }'>
					<Dropdown :data='config?.controls?.data?.(record, index) ?? []' @select='v=>onControl(record, index, v)' :perm='config.perm'/>
				</template>
				<template #switch='{ record, text }'>
					<Switch v-model:value='record[config.enabled.name]' @change='onEnabel($event,record)' />
				</template>
				<template #img='{ record, text }'>
					<Image :src='text' :param='record' />
				</template>
				<template #flowImg='{ record, text }'>
					<Image :src='null' :flow='true' :param='record' />
				</template>
				<template #money='{ record, text }'>
					{{fn.getMoney(text)}}
				</template>
				<template v-for='(col,i) in columns'  #[col.dataIndex]='{ text, record }' :key='i'>
					<template v-if='config.edit || col.edit '>
						<Select v-if="col.type === 'select'" :disabled='fn.getResult(col.disabled)' :data='col.data' :p="'请选择' + col.title" class='w' :idStr='col.idStr' :nameStr='col.nameStr' :api='col.api' v-model:value='record[col.dataIndex]' @change='col?.change({ value:$event.value, row:record })' />
						<DatePicker v-else-if="col.type === 'date'" :p="'请选择' + col.title" :type='col.format' class='w' :form='col.format'  v-model:value='record[col.dataIndex]' :disabled='fn.getResult(col.disabled)'/>
						<Input v-else :p="'请输入' + col.title" v-model:value='record[col.dataIndex]' :type='col.mode' :readOnly='col.readOnly' :disabled='fn.getResult(col.disabled)' @change='col?.change?.($event,record)' />
					</template>
					<template v-else>{{text}}</template>
				</template>
				<!-- 嵌套子表格 -->
				<template v-if='config.hasChild' #expandedRowRender='{ record, index }'>
					<slot name='child' :row='record' :index='index'></slot>
				</template>
			</Table>
		</section>
		<div class='fxm ptb10 rel i10' :class="[ isAuto ? '' : 'tbor1' ]" v-if='fn.hasArray(ajax.data) && config.pag !== false'>
			<slot name='prefix' :data='ajax?.pager'></slot>
			<div class='g9 f12 nowrap'>共 {{ ajax.pager.total ? ajax.pager.total : ajax.data.length}} 条数据</div>
			<Pagination :pager='ajax.pager' :pag="config.pag" class='ex' @change='onChange'/>
		</div>
	</div>
</template>

<script setup>
	import { Table } from 'ant-design-vue'
	import { watch } from 'vue'
	import ControlsUtils from '#cpt/utils/controls'
	import { useRouter } from 'vue-router'
	const router = useRouter()
	const fn = $fn
	const vn = $
	/* --------------------------- Component --------------------------- */
	const Pagination 	= $.lazy(()=>import('@antd/pagination.vue'))
	const Button 		= $.lazy(()=>import('@antd/button.vue'))
	const Switch 		= $.lazy(()=>import('@antd/form/switch.vue'))
	const Image 		= $.lazy(()=>import('@antd/image.vue'))
	const Input 		= $.lazy(()=>import('@antd/form/input.vue'))
	const Select 		= $.lazy(()=>import('@antd/form/select.vue'))
	const DatePicker 	= $.lazy(()=>import('@antd/form/date-picker.vue'))
	const Dropdown		= $.lazy(()=>import('@antd/dropdown.vue'))
	const Controls 	= $.lazy(()=>import('#cpt/temp/Controls.vue'))
	/* --------------------------- props --------------------------- */
	const props = defineProps({
		config 		: { type: Object, default: { cols:[], enabled:{}, data:[] } },
		size 		: { type: String, default:({ config }) => config.size ?? 'small'},
		bordered 	: { type: Boolean, default:({ config }) => {
			const border = config.bordered ?? $config.antd.table.bordered
			return border !== false 
		}  },
		gap 		: { type: Number, default:({ config }) => config.gap ?? $config.btnSpace },
		init 		: { type: [Number, Boolean], default:({ config }) => config.init ?? true },
		search 		: { type: Object, default: { data:[] } },
		data 		: { type: Array, default: []  },
		value 		: { type: Array, default: [] },
		loading 	: Boolean,
		isSubmitForm: Boolean
	})
	const { config, search, value, isSubmitForm } = props
	let { idStr=$config.pullIdName, ref, data=[] } = config
	
	let ajax = $ref({ data: $fn.hasArray( data ) ? data : props.data, pager:{}, onLoading: config.onLoading })
	let selectedRowKeys = $ref( isSubmitForm ? value : config?.row?.keys || [] )
	
	const isAuto = config.height === 'auto'
	/* --------------------------- cols --------------------------- */
	const getCols = cols => {
		cols = $fn.getResult( cols )
		
		if($fn.hasArray( cols )){
			cols = cols.filter( v => $fn.hasObject(v) )
		}else{
			return []
		}
		const controls = $fn.getResult(config.controls)
		
		if($fn.hasObject( controls )){
			let controlSize = controls.size ?? 'small'
			if(config.size === 'small'){ controlSize = 'mini' }
			const {  type, right=1 } = controls
			const ctrl = type === 'dropdown' ? $fn.table.controlsSelect : $fn.table.control
			const fixed = right ? 'right' : 'left'
			return right ? [ ...cols, {...ctrl, fixed, ...controls}] : [ {...ctrl, fixed, ...controls}, ...cols]
		}else{
			return cols
		}
	}
	let columns = $ref( getCols(config.cols) )
	
	watch(()=>props.config.cols, value => columns = getCols(value) )
	/* --------------------------- 事件声明 --------------------------- */
	const emit = defineEmits(['edit','init','update:value', 'change','blur'])
	/* --------------------------- checkbox --------------------------- */
	const checkbox = [ 'checkbox', 'radio' ]
	const rowSelection = config.row ? {
		columnWidth: 50,
		// fixed: 'left',
		type:  config.row.type ? checkbox[config.row.type] : checkbox[0],
		// 改变
		onChange(keys, rows){
			config.row.keys = keys
			config.row.rows = rows
			selectedRowKeys = keys
			config?.row?.change?.({keys, rows:getRows})
			emit('update:value', keys)
		},
		onSelect(record, selected, selectedRows){
			
		},
		// 全选
		onSelectAll(selected, rows, changeRows){
			// if(selected){
			// 	config.row.rows = rows
			// 	config.row.keys = rows.map(v => v[idStr])
			// }else{
			// 	config.row.rows = []
			// 	config.row.keys = []
			// }
		},
		getCheckboxProps: record => {
			const { disabledKeys } = config?.row ?? {}
			if( $fn.isFunction(disabledKeys) ){
				const disabled = disabledKeys?.(record)
				record.disabled = disabled
				return { disabled }
			}else{
				if( $fn.hasArray(disabledKeys) ){
					const disabled = disabledKeys.includes( record[idStr] )
					record.disabled = disabled
					return { disabled }
				}else{
					return {}
				}
			}
		}
	} : null
	// 自定义行点击
	const customRow = record => ({
		onClick: () => {
			if( $fn.isObject( config?.row ) ){
				if( record.disabled ){ return }
				let keys = config.row.keys ?? []
				const type = config.row.type
				const key = record[idStr]
						
				if(selectedRowKeys.includes(key)){
					const index = keys.findIndex(v => v === key)
					keys.splice(index, 1)
					config?.row?.onRowFalse?.(record)
				}else{
					const v = record[idStr]
					if(type === 1){
						keys = [ v ]
					}else{
						keys.push(v )
					}
					config?.row?.onRowTure?.(record)
				}
				
				config?.row?.onRow?.({ row: record, keys, rows:getRows })
				
				config.row.keys = selectedRowKeys = keys
				
				config?.row?.change?.({keys, rows:getRows})
				
				emit('update:value', config?.isRows ? rows : keys)
			}else{
				config?.onRow?.( record )
			}
		}
	})
	// 清除 keys
	const clearKeys = () => {
		if(config.row){ config.row.keys = selectedRowKeys = [] }
	}
	// 设置 keys
	const setKeys = keys => config.row.keys = selectedRowKeys = keys
	//设置 rows
	const setRows = row => config.row.keys = selectedRowKeys = row.map( v => v[idStr ])
	// 获取 rows
	const getRows = () => ajax.data.filter( v => config.row.keys.includes( v[idStr]) )
	// 设置行颜色
	const onRowClass = (record, index) => config?.onRowClass?.(record, index)
	// 设置默认值
	if( $fn.hasArray( selectedRowKeys ) ){ config.row.keys = selectedRowKeys }
	/* --------------------------- ajax --------------------------- */
	// 默认加载
	const fetch = option => {
		let { param, query, scroll } = option ?? {}
		let { api, paging, id } = config
		param = $fn.getSubmitParam(search.data, $fn.getResult( param ))
		if(api){
			$http.paging(ajax, api, { param, id, query, paging }).then(({ data, rows })=>{
				
				if(scroll === 1) {
					scrollRest( window.innerHeight )
				}else if(scroll === 0){
					
				}else{
					scrollRest()
				}
				
				config.data = ajax.data
				config?.onSuccess?.(rows ? rows : data, { param, query })
			})
		}
	}
	// 分页切换
	const onChange = (page, size) => {
		fetch({ param:{ page, size }, scroll:true })
		clearKeys()
	}
	// 排序
	const onSort = (pagination, filters, sorter) => {
		let type = null
		if(sorter.order === 'ascend'){			// 升序
			type = 'asc'
		}else if(sorter.order === 'descend'){ 	// 降序
			type = 'desc'
		}else{
			type = 0							// 不排序
		}
		const param = type ? {sort:sorter.field, sort_type: type} : null
		if(param){
			ajax.model = {...ajax.model, ...param}
		}else{
			delete ajax.model.sort
			delete ajax.model.sort_type
		}
		fetch({scroll:true})
	}
	/* --------------------------- 默认请求列表 --------------------------- */
	// 获取默认参数
	const getParam = data => {
		let param = {}
		if($fn.hasArray(data)){
			data.forEach(v=> {
				if( $fn.isValid(v.value) ){
					param[v.name] = v.value
				}
			})
		}
		return param
	}
	
	const onInitFetch = () => {
		const param = getParam(search.data)
		// ajax.model = $fn.getResult(search?.param)
		// ajax.query = $fn.getResult(search?.query)
		fetch({ param:{ ...param, ...search?.param }, query:search?.query, scroll:true }) 
	}
	if( props.init ){ 
		onInitFetch()
	}
	/* --------------------------- watch --------------------------- */
	watch(()=>props.config.row?.keys, value => {
		if(Array.isArray( value )){ setKeys( value ) }
	})
	watch(()=>props.value, value=>{
		if(Array.isArray( value )){ setKeys( value ) }
	})

	watch(()=>props.config.data, value => ajax.data = value ?? [] )
	/* --------------------------- 表格操作 --------------------------- */
	let tableRef = $ref()
	const scrollTop = value => {
		if(tableRef){
			if($fn.isNumber(value)){
				tableRef.querySelector('.ant-table-body').scrollTop = value
			}else{
				return tableRef.querySelector('.ant-table-body').scrollTop
			}
		}
	}
	const scrollRest = value => {
		if( !isAuto ){ scrollTop( value ?? 0) }
	}
	// 启用与禁用
	const onEnabel = (value, record) => {
		$http.put(null, config.enabled.api, { param:{ [config.enabled.name]: value, [$config.postIdName]: record[idStr] }, onError:()=>{
			record[idStr] = 0
			fetch()
			$fn.msg.warnig( +value === 1 ? '启用失败' : '禁用失败' )
		} }).then(()=>{
			$fn.msg.success( +value === 1 ? '启用成功' : '禁用成功' )
		})
	}
	/* --------------------------- 默认加载 --------------------------- */
	let scrollY = 0
	const isPaging =  config.paging !== 0 && config.paging !== false
	/* --------------------------- 通信 --------------------------- */
	const f = {
		refresh : scroll => fetch({ scroll: scroll??true }),
		search: option => {
			const { param, query, scroll=true } = option ?? {}
			fetch( { param: isPaging ? { ...param, page: 1} : param, query, scroll })
			clearKeys()
		},
		cacheRefresh: param => {
			fetch({ param })
			scrollTop(scrollY)
		},
		reset: () => {
			ajax.model = isPaging ? { page:1, size:ajax.pager?.size ?? $config.paging.pageSize } : {}
			onInitFetch()
		},
		refreshClear: (scroll)=>{
			fetch({ scroll: scroll??true })
			clearKeys()
		},
		getParam: () => ajax?.pager?.param, 		// 获取所有参数
		// keys
		clearKeys,
		setKeys,
		getKeys: () => $fn.getArray( config?.row?.keys ),
		keys: v => Array.isArray(v) ? setKeys( v ) : $fn.getArray( config?.row?.keys ),
		rows: v => Array.isArray(v) ? setRows( v ) : $fn.getRows( ),
		// data
		data: v => Array.isArray(v) ? ajax.data = config.data = v : ajax.data,
	}
	// 按钮点击
	const onControl = (record, index, option) => ControlsUtils({option, index, tableConfig:{ ...config, record, tableRef:f }, router })
	// 设置权限
	// const setPerm = data => $fn.setPerm( data, config.perm )
	/* --------------------------- 默认加载 --------------------------- */
	$.onMounted(()=>{
		const p = { tableRef:f }
		emit('init', p)
		config?.onInit?.( p )
		if(config.saveScroll){
			tableRef.querySelector('.ant-table-body').onscroll = function(){
				scrollY = this.scrollTop
			}
		}
	})
	
	defineExpose(f)
</script>
<style>
	.ant-table-header-column{width:100%}
	.ant-table-column-sorters{display: flex!important; align-items: center;}
	.ant-table-column-title{flex:1}
</style>